/*
 * Created by SharpDevelop.
 * User: David
 * Date: 2006-12-25
 * Time: 00:59
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */

using System;
using System.Diagnostics;

using patterns;

using Labb4.Pooman.Cards;
using Labb4.Pooman.Players;
using Labb4.Pooman.Game;

namespace Labb4.Rules
{
	/// <summary>
	/// Rules for different things are stored here
	/// 
	/// Implements the Singleton design pattern
	/// Implements the Observer design pattern
	/// </summary>
	public sealed class PoomanRules : Observer<GameState>
	{
		#region members
		
		/// <summary>
		/// The one instance
		/// </summary>
		private static PoomanRules		m_Instance = new PoomanRules();
		
		/// <summary>
		/// Reference to the current set of rules
		/// </summary>
		private SetOfRules				m_Rules;
		/// <summary>
		/// Rules to the first phase of the game
		/// </summary>
		private SetOfRulesPhase1		m_RulesPhase1;
		/// <summary>
		/// Rules to the second phase of the game
		/// </summary>
		private SetOfRulesPhase2		m_RulesPhase2;
		
		/// <summary>
		/// Reference to the current round being played
		/// </summary>
		private Round					m_CurrentRound;
		/// <summary>
		/// The current trump
		/// </summary>
		private Trump					m_CurrentTrump;
		/// <summary>
		/// Reference to the main game
		/// </summary>
		private PoomanMain				m_PoomanMain;
		
		/// <summary>
		/// A deck of cards used when loading and saving
		/// </summary>
		private Deck					Cards;
		
		#endregion
		
		#region constructors
		
		/// <summary>
		/// Constructor, initializes members
		/// </summary>
		private PoomanRules() :
			base()
		{
			m_Rules = null;
			m_RulesPhase1 = new SetOfRulesPhase1();
			m_RulesPhase2 = new SetOfRulesPhase2();
			
			m_CurrentRound = null;
			m_CurrentTrump = null;
			m_PoomanMain = null;
			Cards = null;
		}
		
		#endregion
		
		#region methods
		
		/// <summary>
		/// The playable cards in the current context
		/// </summary>
		/// <param name="cards">The cards to check among</param>
		/// <returns>The cards from the sent cardpile that are currently playable</returns>
		public CardPile PlayableCards(CardPile cards)
		{
			return m_Rules.PerformCheckForPlayability(cards, m_CurrentRound, m_CurrentTrump);
		}
		
		/// <summary>
		/// Uses the current set of rules to deal cards to players
		/// </summary>
		/// <param name="player">The player to deal a card to</param>
		public void DealCardsToPlayer(Player player)
		{
			m_Rules.PerformDealCards(player, m_PoomanMain);
		}
		
		/// <summary>
		/// Prepare for loading by generating a brand new deck of cards for all different
		/// card holders to get cards from
		/// </summary>
		public void PrepareForLoad()
		{
			Cards = new Deck();
			Cards.ResetAllCards();
		}
		
		/// <summary>
		/// After loading has completed this checkup method is called
		/// </summary>
		public void FinnishUpLoad()
		{
			if(Cards.Count > 0)
			{
				//This happens in phase 2
				Cards.Clear();
			}
			
			Cards = null;
		}
		
		/// <summary>
		/// Gets a reference to a card from the brand new deck created in the method <see cref="this.PrepareForLoad">PrepareForLoad</see>
		/// </summary>
		/// <param name="suit">The suit of the card to get</param>
		/// <param name="rank">The rank of the card to get</param>
		/// <returns></returns>
		public Card GetCard(Card.Suit suit, Card.Rank rank)
		{
			return Cards.GetAndRemoveCard(suit, rank);
		}
		
		#endregion
		
		#region overrides
		
		/// <summary>
		/// Uses the new state of the base class to select the state of this class
		/// </summary>
		protected override void UpdateObserver()
		{
			base.UpdateObserver();
			
			if(m_SubjectsState is GameStatePhase1)
			{
				m_Rules = m_RulesPhase1;
			}
			else
			{
				m_Rules = m_RulesPhase2;
			}
		}
		
		#endregion
		
		#region properties
		
		/// <summary>
		/// The one instance (get)
		/// </summary>
		public static PoomanRules Instance
		{
			get
			{
				return m_Instance;
			}
		}
		
		/// <summary>
		/// A reference to the currently played round (set/get)
		/// </summary>
		public Round CurrentRound
		{
			get
			{
				return m_CurrentRound;
			}
			
			set
			{
				m_CurrentRound = value;
			}
		}
		
		/// <summary>
		/// Reference to the current trump (set/get)
		/// </summary>
		public Trump CurrentTrump
		{
			get
			{
				return m_CurrentTrump;
			}
			
			set
			{
				m_CurrentTrump = value;
			}
		}
		
		/// <summary>
		/// Reference to the current PoomanMain instance (set/get)
		/// When the PoomanMain is set, this instance automagically subscribes to it
		/// </summary>
		public PoomanMain MainPoo
		{
			get
			{
				return m_PoomanMain;
			}
			
			set
			{
				m_PoomanMain = value;
				Subscribe(value);
			}
		}
		
		/// <summary>
		/// Reference to the current rules (get)
		/// </summary>
		public SetOfRules Rules
		{
			get
			{
				return m_Rules;
			}
		}
		
		#endregion
	}
}
